package cn.tedu.shoot;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.net.MalformedURLException;
import java.util.Arrays;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

public class World extends JPanel implements Runnable, KeyListener {
    java.applet.AudioClip bg;
    private Sky sky = new Sky();
    private Hero hero = new Hero(World.WIDTH / 2 - Hero.WIDTH / 2 - 100, 500);
    private Hero hero2 = new Hero(World.WIDTH / 2 - Hero.WIDTH / 2 + 100, 500);
    private Boss boss;
    private FlyingObject[] enemies = {};
    private Bullet[] bullets = {};
    private Bullet[] bullets2 = {};
    private BossBullet[] bullets1 = {};
    private BossBullet[] bullets3 = {};
    private int score = 0;
    private int score2 = 0;
    int enterIndex = 0;
    int shootIndex = 0;
    public static final int WIDTH = 512, HEIGHT = 768;
    public static final int START = 0;
    public static final int RUNNING = 1;
    public static final int PAUSE = 2;
    public static final int GAME_OVER = 3;
    private int state = START;

    public int getScore() {
        return score;
    }

    public int getScore2() {
        return score2;
    }

    public World() {
        try {
            bg = JApplet.newAudioClip(new File("C:\\Users\\Lance\\IdeaProjects\\my-shoot\\src\\cn\\tedu\\shoot\\bgm.wav").toURI().toURL());

        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        this.action();
    }

    //随机生成敌机
    public FlyingObject nexOne() {//随机产生敌机
        Random random = new Random();
        int type = random.nextInt(19);
        if (type < 5) {
            return new Bee();
        } else if (type < 13) {
            return new Airplane();

        } else {
            return new BigAirplane();
        }

    }

    //定时器操控敌机入场
    public void enterAction() {//
        enterIndex++;
        FlyingObject obj = nexOne();
        if (boss == null && enterIndex % 40 == 0) {
            enemies = Arrays.copyOf(enemies, enemies.length + 1);
            enemies[enemies.length - 1] = obj;
        }
        if ((score+score2 + 1) % 100 > 95 && boss == null) {//
            boss = new Boss();

        }
        //System.out.println("敌方飞行物数量：" + enemies.length);
    }

    //定时器操控子弹入场
    public void shootAction() {
        shootIndex++;
        if (shootIndex % 30 == 0) {
            Bullet[] bs = hero.shoot();
            bullets = Arrays.copyOf(bullets, bullets.length + bs.length);
            System.arraycopy(bs, 0, bullets, bullets.length - bs.length, bs.length);
        }
        if (shootIndex % 30 == 0) {
            Bullet[] bs = hero2.shoot();
            bullets2 = Arrays.copyOf(bullets2, bullets2.length + bs.length);
            System.arraycopy(bs, 0, bullets2, bullets2.length - bs.length, bs.length);
        }


        if (boss != null && shootIndex % 100 == 0 && boss.isLive()) {
            BossBullet[] bossbs = boss.shoot();
            bullets1 = Arrays.copyOf(bullets1, bullets1.length + bossbs.length);
            System.arraycopy(bossbs, 0, bullets1, bullets1.length - bossbs.length, bossbs.length);
        }


    }

    //飞行物移动
    public void stepAction() {
        sky.step();

        for (int i = 0; i < enemies.length; i++) {
            FlyingObject f = enemies[i];
            f.step();
        }
        for (int i = 0; i < bullets.length; i++) {
            Bullet b = bullets[i];
            b.step();
        }
        for (int i = 0; i < bullets2.length; i++) {
            Bullet b = bullets2[i];
            b.step();
        }
        for (int i = 0; i < bullets1.length; i++) {
            BossBullet b = bullets1[i];
            b.step1();
        }
        for (int i = 0; i < bullets3.length; i++) {
            BossBullet b = bullets3[i];
            b.step1();
        }
        if (boss != null) {
            if (boss.y < HEIGHT / 3 - boss.HEIGHT) {
                boss.step();
            } else if (boss.isLive()) {
                boss.step2();
            } else {
                boss.step3();
            }
        }
    }

    //飞行物删除
    public void outOfBoundsAction() {
        for (int i = 0; i < enemies.length; i++) {
            if (enemies[i].isOutOfBounds() || enemies[i].isRemove()) {
                enemies[i] = enemies[enemies.length - 1];
                enemies = Arrays.copyOf(enemies, enemies.length - 1);
            }
        }
        for (int i = 0; i < bullets.length; i++) {
            if (bullets[i].isOutOfBounds() || bullets[i].isRemove()) {
                bullets[i] = bullets[bullets.length - 1];
                bullets = Arrays.copyOf(bullets, bullets.length - 1);
            }
        }
        for (int i = 0; i < bullets1.length; i++) {
            if (bullets1[i].isOutOfBounds() || bullets1[i].isRemove()) {
                bullets1[i] = bullets1[bullets1.length - 1];
                bullets1 = Arrays.copyOf(bullets1, bullets1.length - 1);
            }
        }
        if (boss != null && boss.isRemove()) {
            boss = null;
        }


    }

    //英雄机子弹碰撞
    public void bulletBangAction() {
        for (int i = 0; i < bullets.length; i++) {
            Bullet b = bullets[i];
            for (int j = 0; j < enemies.length; j++) {
                FlyingObject f = enemies[j];

                if (b.isLive() && f.isLive() && f.isHit(b)) {
                    b.goDead();
                    f.goDead();
                    if (f instanceof EnemyScore) {
                        EnemyScore es = (EnemyScore) f;
                        score += es.getScore();
                    }
                    if (f instanceof EnemyAward) {
                        EnemyAward ea = (EnemyAward) f;
                        int type = ea.getAwardType();
                        switch (type) {
                            case EnemyAward.FIRE:
                                hero.addFire();
                                break;
                            case EnemyAward.LIFE:
                                hero.addLife();
                                break;

                        }
                    }

                }
            }
            if (boss != null && b.isLive() && boss.isHit(b)) {
                boss.subtractLife();
                b.goDead();
                if (boss.getLife() <= 0 && boss.isLive()) {
                    boss.goDead();
                    if (boss instanceof EnemyScore) {
                        EnemyScore es = (EnemyScore) boss;
                        score += es.getScore();
                    }

                }
            }
        }
        for (int i = 0; i < bullets2.length; i++) {
            Bullet b = bullets2[i];
            for (int j = 0; j < enemies.length; j++) {
                FlyingObject f = enemies[j];

                if (b.isLive() && f.isLive() && f.isHit(b)) {
                    b.goDead();
                    f.goDead();
                    if (f instanceof EnemyScore) {
                        EnemyScore es = (EnemyScore) f;
                        score2 += es.getScore();
                    }
                    if (f instanceof EnemyAward) {
                        EnemyAward ea = (EnemyAward) f;
                        int type = ea.getAwardType();
                        switch (type) {
                            case EnemyAward.FIRE:
                                hero2.addFire();
                                break;
                            case EnemyAward.LIFE:
                                hero2.addLife();
                                break;

                        }
                    }

                }
            }
            if (boss != null && b.isLive() && boss.isHit(b)) {
                boss.subtractLife();
                b.goDead();
                if (boss.getLife() <= 0 && boss.isLive()) {
                    boss.goDead();
                    if (boss instanceof EnemyScore) {
                        EnemyScore es = (EnemyScore) boss;
                        score2 += es.getScore();
                    }

                }
            }
        }
    }

    //英雄机碰撞
    public void heroBangAction() {
        for (int i = 0; i < enemies.length; i++) {
            FlyingObject f = enemies[i];
            if (hero.isLive() && f.isLive() && f.isHit(hero)) {
                f.goDead();
                if (hero.shield) {
                    hero.switchShield();
                } else {
                    hero.clearFire();
                    hero.subtractHp();
                }

            }
            if (hero2.isLive() && f.isLive() && f.isHit(hero2)) {
                f.goDead();
                if (hero2.shield) {
                    hero2.switchShield();
                } else {
                    hero2.clearFire();
                    hero2.subtractHp();
                }

            }
        }
        for (int i = 0; i < bullets1.length; i++) {
            BossBullet b = bullets1[i];
            if (hero.isLive() && b.isLive() && b.isHit(hero)) {
                b.goDead();
                if (hero.shield) {
                    hero.switchShield();
                } else {
                    hero.subtractHp();
                }
            }
            if (hero2.isLive() && b.isLive() && b.isHit(hero2)) {
                b.goDead();
                if (hero2.shield) {
                    hero2.switchShield();
                } else {
                    hero2.subtractHp();
                }
            }
        }
        if (hero.getHp() <= 0) {
            if (hero.getLive() > 0) {
                hero.subtractLife();
            } else {
                hero2.subtractLife();
            }
            hero.addHp();
        }
        if (hero2.getHp() <= 0) {
            if (hero2.getLive() > 0) {
                hero2.subtractLife();
            } else {
                hero.subtractLife();
            }
            hero2.addHp();
        }


    }

    //游戏结束
    public void checkGameOverAction() {

        if (hero.getLive() <= 0 && hero2.getLive() <= 0) {
            state = GAME_OVER;
            Rank rank=new Rank();
            rank.rank();
        }
    }

    public void action() {//测试代码

        MouseAdapter m = new MouseAdapter() {

            public void mouseMoved(MouseEvent e) {
                if (state == RUNNING) {
                    int x = e.getX();
                    int y = e.getY();
                    hero2.moveTo(x, y);

                }
            }

            public void mouseClicked(MouseEvent e) {
                switch (state) {
                    case START:
                        state = RUNNING;
                        break;
                    case GAME_OVER:
                        score = 0;
                        /* sky = new Sky();*/
                        hero = new Hero(World.WIDTH / 2 - WIDTH / 2 - 100, 500);
                        hero2 = new Hero(World.WIDTH / 2 - WIDTH / 2 + 100, 500);
                        enemies = new FlyingObject[0];
                        bullets = new Bullet[0];
                        state = START;
                        break;

                }
            }

            public void mouseExited(MouseEvent e) {
                if (state == RUNNING) {//运行状态时
                    state = PAUSE;//修改为暂停状态
                    bg.stop();
                }
            }

            public void mouseEntered(MouseEvent e) {
                if (state == PAUSE) {//暂停状态时
                    state = RUNNING;   //修改为运行状态
                    bg.loop();
                }
            }
        };
        bg.loop();

        this.addMouseListener(m);
        this.addMouseMotionListener(m);
        Timer timer = new Timer();
        int interval = 10;
        timer.schedule(new

                               TimerTask() {
                                   public void run() {
                                       if (state == RUNNING) {
                                           hero.step();
                                           enterAction();
                                           shootAction();
                                           /*System.out.println(enemies.length + "," + bullets.length);*/
                                           stepAction();
                                           outOfBoundsAction();
                                           bulletBangAction();
                                           heroBangAction();
                                           checkGameOverAction();
                                       }
                                       repaint();

                                   }
                               }, interval, interval);
    }

    //画
    public void paint(Graphics g) {
        g.drawImage(sky.getImage(), sky.x, sky.y, null);
        g.drawImage(sky.getImage(), sky.x, sky.getY1(), null);
        g.drawImage(hero.getImage(), hero.x, hero.y, null);
        g.drawImage(hero2.getImage(), hero2.x, hero2.y, null);
        g.setColor(new Color(255, 0, 0));
        g.drawRect(hero.x, hero.y + hero.height, 100, 15);
        g.drawRect(hero2.x, hero2.y + hero2.height, 100, 15);
        g.fillRect(hero.x + 2, hero.y + hero.height + 2, hero.getHp() - 3, 15 - 3);
        g.fillRect(hero2.x + 2, hero2.y + hero2.height + 2, hero2.getHp() - 3, 15 - 3);
        if (hero.shield) {
            g.drawImage(Images.shield, hero.x + (hero.width - 156) / 2, hero.y + (hero.height - 156) / 2, null);
        }
        if (hero2.shield) {
            g.drawImage(Images.shield, hero2.x + (hero2.width - 156) / 2, hero2.y + (hero2.height - 156) / 2, null);
        }


        if (boss != null) {
            if (boss.isDead()) {
                g.drawImage(boss.getImage(), boss.x + 80, boss.y, null);
            } else {
                g.drawImage(boss.getImage(), boss.x, boss.y, null);
            }
            if (boss.isLive()) {
                g.drawRect(boss.x, boss.y - 20, boss.width, 20);
                g.fillRect(boss.x + 2, boss.y - 20 + 2, boss.getLife() - 3, 20 - 3);
            }
        }
        for (int i = 0; i < enemies.length; i++) {
            FlyingObject f = enemies[i];
            g.drawImage(f.getImage(), f.x, f.y, null);

        }
        for (int i = 0; i < bullets.length; i++) {
            Bullet b = bullets[i];
            g.drawImage(b.getImage(), b.x, b.y, null);
        }
        for (int i = 0; i < bullets2.length; i++) {
            Bullet b = bullets2[i];
            g.drawImage(b.getImage(), b.x, b.y, null);
        }
        for (int i = 0; i < bullets1.length; i++) {
            BossBullet b = bullets1[i];
            g.drawImage(b.getImage(), b.x, b.y, null);
        }
        g.drawString("SCORE:" + score, 10, 25);
        g.drawString("SCORE:" + score2, WIDTH - 110, 25);
        g.drawString("LIFE:" + hero.getLive(), 10, 45);
        g.drawString("LIFE:" + hero2.getLive(), WIDTH - 110, 45);
        switch (state) {
            case START:
                g.drawImage(Images.start, 0, 0, null);
                break;
            case PAUSE:
                g.drawImage(Images.pause, 0, 0, null);
                break;
            case GAME_OVER:
                g.drawImage(Images.gameover, 0, 0, null);

        }

    }

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        World world = new World();
        frame.add(world);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(WIDTH, HEIGHT);

        frame.setLocationRelativeTo(null);
        frame.setVisible(true);//1)设置窗口可见  2）尽快调用paint方法
        /*  world.action();//启动程序的执行*/
        frame.addKeyListener(world);
        Thread t = new Thread(world);
        t.start();

    }


    @Override
    public void keyTyped(KeyEvent e) {


    }

    @Override
    public void keyPressed(KeyEvent e) {
        if (score > 50 && e.getKeyCode() == KeyEvent.VK_SPACE) {
            for (int i = 0; i < enemies.length; i++) {
                enemies[i].goDead();

            }
            for (int i = 0; i < bullets1.length; i++) {
                bullets1 = new BossBullet[]{};
            }
            score -= 50;
        }
        if (score2 > 50 && e.getKeyCode() == KeyEvent.VK_K) {
            for (int i = 0; i < enemies.length; i++) {
                enemies[i].goDead();

            }
            for (int i = 0; i < bullets1.length; i++) {
                bullets1 = new BossBullet[]{};
            }
            score2 -= 50;
        }
        if (e.getKeyCode() == KeyEvent.VK_W) {
            hero.setwSpeed(3);
        }
        if (e.getKeyCode() == KeyEvent.VK_S) {
            hero.setsSpeed(3);

        }
        if (e.getKeyCode() == KeyEvent.VK_A) {
            hero.setaSpeed(3);

        }
        if (e.getKeyCode() == KeyEvent.VK_D) {
            hero.setdSpeed(3);

        }
        if (e.getKeyCode() == KeyEvent.VK_F && score >= 10 && !hero.shield) {
            hero.switchShield();
            score -= 10;
        }
        if (e.getKeyCode() == KeyEvent.VK_L && score2 >= 10 && !hero2.shield) {
            hero2.switchShield();
            score2 -= 10;
        }


    }

    @Override
    public void keyReleased(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_W) {
            hero.setwSpeed(0);
        }
        if (e.getKeyCode() == KeyEvent.VK_S) {
            hero.setsSpeed(0);

        }
        if (e.getKeyCode() == KeyEvent.VK_A) {
            hero.setaSpeed(0);

        }
        if (e.getKeyCode() == KeyEvent.VK_D) {
            hero.setdSpeed(0);
        }

    }
}
